package JUC;


import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class ShareData{
    private int number = 1;//A:1,B:2,C:3

    private Lock lock = new ReentrantLock();
    //需要三个钥匙标志位代表唤醒不同线程
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();

    private void fun(int index){
        for (int i = 0; i < index; i++) {
            System.out.println(Thread.currentThread().getName()+"\t"+(i+1));
        }
    }

    public void printMsg(int flag){
        lock.lock();
        try {
            if (flag ==5){
                while (number !=1){
                    condition1.await();
                }
                this.fun(flag);
                this.number = 2;
                condition2.signal();
            }

            if (flag ==10 ){
                while (number !=2){
                    condition2.await();
                }
                this.fun(flag);
                this.number = 3;
                condition3.signal();
            }
            if (flag == 15){
                while (number !=3){
                    condition3.await();
                }
                this.fun(flag);
                this.number = 1;
                condition1.signal();
            }

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}
/**
 * 备注：多线程之间按顺序调用，实现A->B->C
 * 三个线程启动，要求如下：
 * A打印5次，B打印10次，C打印15次
 * 接着
 * A打印5次，B打印10次，C打印15次
 * 来10轮
 *      1.高内聚低耦合前提下，线程操作资源类
 *      2.判断/干活/通知
 *      3.多线程交互中，防止虚假唤醒(判断只能用while，不能用if)
 *      4.标志位
 */


public class ConditionDemo {

    public static void main(String[] args) {
        ShareData shareData = new ShareData();
        new Thread(()->{
                    //insert your code here
            for (int i = 0; i < 10; i++) {
                shareData.printMsg(5);
            }
                },"A").start();
        new Thread(()->{
                    //insert your code here
            for (int i = 0; i < 10; i++) {
                shareData.printMsg(10);
            }
                },"B").start();
        new Thread(()->{
                    //insert your code here
            for (int i = 0; i < 10; i++) {
                shareData.printMsg(15);
            }
                },"C").start();


    }
}
